/*
 * Copyright 2013 JROSE
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jrose.test.support;

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.jrose.api.annotation.persistence.Table;
import org.jrose.test.annotation.CleanupTables;
import org.jrose.test.annotation.CleanupUsers;
import org.junit.runners.model.FrameworkMethod;

import javax.sql.DataSource;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;

/**
 * Prepare database tables in unit test environment.
 *
 * @author Xiaohai Zhang
 * @since 2013-08-17 16:24
 */
@RequiredArgsConstructor
public class PrepareDatabaseTables {
    @NonNull private final FrameworkMethod method;
    @NonNull private final DataSource dataSource;

    public void prepare() {
        Set<String> candidates = candidates(method);
        if (candidates.isEmpty()) {
            return;
        }
        TableScriptManager.initialize(dataSource);
        for (String tableName : candidates) {
            TableScriptManager.getScript(dataSource, tableName).cleanup();
        }
    }

    private Set<String> candidates(FrameworkMethod method) {
        Set<String> allTables = new TreeSet<>();

        CleanupTables cleanupTables = method.getAnnotation(CleanupTables.class);
        if (cleanupTables != null) {
            if (ArrayUtils.isNotEmpty(cleanupTables.tables())) {
                allTables.addAll(Arrays.asList(cleanupTables.tables()));
            }
            handleWithEntities(allTables, cleanupTables.entities());
        }

        CleanupUsers cleanupUsers = method.getAnnotation(CleanupUsers.class);
        if (cleanupUsers != null) {
            handleWithEntities(allTables, cleanupUsers.entities());
        }

        return allTables;
    }

    private void handleWithEntities(Set<String> allTables, Class<? extends Serializable>[] entityClasses) {
        if (ArrayUtils.isEmpty(entityClasses)) {
            return;
        }
        for (Class<? extends Serializable> entityClass : entityClasses) {
            if (entityClass == null) {
                continue;
            }
            Table table = entityClass.getAnnotation(Table.class);
            if (table == null || StringUtils.isBlank(table.value())) {
                continue;
            }
            allTables.add(table.value());
        }
    }
}
